use std::collections::HashMap;
use std::sync::Arc;

use async_trait::async_trait;
use mf_core::types::Extensions;
use price_rules::loader::RulesLoaderExt;
use tokio::runtime::Runtime;
use zen_engine::loader::{LoaderError, LoaderResult};
use zen_engine::model::DecisionContent;

use super::{
    BootstrapContext, BootstrapRegistry, BootstrapResult, DataSourceProvider, ExtensionProvider, MetadataProvider, ProjectPhase, ProjectProfile,
    ProviderSelector, RuleProvider,
};

/// 空 schema 提供器，用于测试
struct EmptySchema;

#[async_trait]
impl ExtensionProvider for EmptySchema {
    async fn provide(
        &self,
        _: &ProjectProfile,
    ) -> BootstrapResult<Vec<Extensions>> {
        Ok(Vec::new())
    }

    fn name(&self) -> &'static str {
        "test-schema"
    }
}

/// 固定元数据提供器
struct StaticMetadata;

#[async_trait]
impl MetadataProvider for StaticMetadata {
    async fn provide(
        &self,
        _: &ProjectProfile,
    ) -> BootstrapResult<HashMap<String, String>> {
        let mut map = HashMap::new();
        map.insert("phase".to_string(), "budget".to_string());
        Ok(map)
    }

    fn name(&self) -> &'static str {
        "test-metadata"
    }
}

/// 数据源提供器，向上下文注册内存数据源
struct DummyDataSource;

#[async_trait]
impl DataSourceProvider for DummyDataSource {
    async fn configure(
        &self,
        _: &ProjectProfile,
        ctx: &mut BootstrapContext,
    ) -> BootstrapResult<()> {
        ctx.register_data_source_owned("memory", 1_i32);
        Ok(())
    }

    fn name(&self) -> &'static str {
        "test-data-source"
    }
}

/// 简单规则加载器
#[derive(Debug)]
struct DummyRulesLoader;

#[async_trait]
impl RulesLoaderExt for DummyRulesLoader {
    async fn load_rule(
        &self,
        key: &str,
    ) -> LoaderResult<DecisionContent> {
        Err(LoaderError::NotFound(key.to_string()).into())
    }
}

/// 规则提供器返回上述加载器
struct DummyRuleProvider;

#[async_trait]
impl RuleProvider for DummyRuleProvider {
    async fn provide(
        &self,
        _: &ProjectProfile,
    ) -> BootstrapResult<Arc<dyn RulesLoaderExt>> {
        Ok(Arc::new(DummyRulesLoader))
    }

    fn name(&self) -> &'static str {
        "test-rule"
    }
}
